home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / dbg / sun3.md / dbgMain.c < prev    next >
C/C++ Source or Header  |  1991-06-28  |  36KB  |  1,362 lines

  1. /* dbgMain.c -
  2.  *
  3.  *     This contains the routines which read and execute commands from kdbx.
  4.  *
  5.  *     All reads and writes to kdbx occur over channel A of the Rs232 line.
  6.  *
  7.  * Copyright (C) 1985 Regents of the University of California
  8.  * All rights reserved.
  9.  */
  10.  
  11. #ifndef lint
  12. static char rcsid[] = "$Header: /sprite/src/kernel/dbg/sun3.md/RCS/dbgMain.c,v 9.10 91/06/28 12:07:08 mgbaker Exp $ SPRITE (Berkeley)";
  13. #endif /* not lint */
  14.  
  15. #include <sprite.h>
  16. #include <dbg.h>
  17. #include <dbgInt.h>
  18. #include <main.h>
  19. #include <mach.h>
  20. #include <proc.h>
  21. #include <vm.h>
  22. #include <vmInt.h>
  23. #include <vmMach.h>
  24. #include <vmMachInt.h>
  25. #include <machMon.h>
  26. #include <net.h>
  27. #include <netEther.h>
  28. #include <netInet.h>
  29. #include <dev.h>
  30. #include <devVid.h>
  31. #include <bstring.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34.  
  35. Boolean    dbg_BeingDebugged = FALSE;        /* TRUE if are under control
  36.                          * of kdbx.*/
  37. Boolean    dbg_UsingNetwork = FALSE;        /* TRUE if the debugger is
  38.                          * using the network interface*/
  39. char    requestBuffer[DBG_MAX_REQUEST_SIZE];    /* Buffer to receive request
  40.                          * into. */
  41. int    requestOffset;                /* Offset in buffer where next
  42.                          * bytes should be read from.*/
  43. char    replyBuffer[DBG_MAX_REPLY_SIZE];    /* Buffer to hold reply. */
  44. int    replyOffset = 0;            /* Offset in buffer where next
  45.                          * bytes in reply should go. */
  46. int    curMsgNum;                /* The current message that
  47.                          * is being processed. */
  48. int    dbgMonPC;                /* Place to get the PC from
  49.                          * if trap via the monitor.*/
  50. int    dbgTraceLevel;                /* The debugger tracing
  51.                          * level. */
  52. Boolean dbg_SyncedDisks = FALSE;                /* For determining in the
  53.                                                  * debugger whether the disks
  54.                                                  * got sync'd or not. */
  55.  
  56. /*
  57.  * Number of times to poll before timing out and resending (about 2 seconds).
  58.  */
  59. #ifdef sun3
  60. int    dbgTimeout = 50000;
  61. #else
  62. int    dbgTimeout = 15000;
  63. #endif
  64.  
  65. /*
  66.  * Information about the latest packet received.
  67.  */
  68. Boolean            gotPacket;    
  69. int            dbgPacketLength;
  70. Net_InetAddress        dbgMyIPAddr;
  71. Net_InetAddress        dbgSrcIPAddr;
  72. Net_InetAddress        dbgSrcPort;
  73. Net_EtherHdr        dbgEtherHdr;
  74. Net_ScatterGather    dbgGather;
  75. Net_Interface        *dbgInterPtr = (Net_Interface *) NIL;
  76.  
  77. /*
  78.  * Size of debugging packet header and data.
  79.  */
  80. #define    PACKET_HDR_SIZE (sizeof(Net_EtherHdr) + Dbg_PacketHdrSize() + 4)
  81. #define PACKET_DATA_SIZE (DBG_MAX_REPLY_SIZE - PACKET_HDR_SIZE)
  82.  
  83. /*
  84.  * Strings which describe each of the opcodes that kdbx can send us.
  85.  */
  86. static char *opcodeNames[] =  {
  87.     "Read all GPRS",
  88.     "Write GPR",
  89.     "Continue",
  90.     "Single Step",
  91.     "Detach",
  92.     "Inst Read",
  93.     "Inst Write",
  94.     "Data Read",
  95.     "Data Write",
  96.     "Process to walk stack for",
  97.     "Read information after stopped",
  98.     "Return version string",
  99.     "Divert syslog to the console",
  100.     "Reboot the machine",
  101.     "Set up things to start a call command",
  102.     "Clean up things after a call command has executed",
  103.     "UNKNOWN OPCODE"
  104. };
  105.  
  106. /*
  107.  * Strings which describe the different exceptions that can occur.
  108. */
  109. static char *exceptionNames[] = {
  110.   /* 0 */   "Reset",
  111.   /* 1 */   "UNKNOWN EXCEPTION",
  112.   /* 2 */   "Bus Error",
  113.   /* 3 */   "Address Error",
  114.   /* 4 */   "Illegal Instruction",
  115.   /* 5 */   "Zero Div",
  116.   /* 6 */   "CHK Instruction",
  117.   /* 7 */   "TrapV",
  118.   /* 8 */   "Privilege Violation",
  119.   /* 9 */   "Trace Trap",
  120.   /* 10 */  "EMU 1010",
  121.   /* 11 */  "EMU 1111",
  122.   /* 12 */  "UNKNOWN EXCEPTION",
  123.   /* 13 */  "Coprocessor Protocol Violation",
  124.   /* 14 */  "Stack Format Error",
  125.   /* 15 */  "Uninitialized Vector",
  126.   /* 16 */  "UNKNOWN EXCEPTION",
  127.   /* 17 */  "UNKNOWN EXCEPTION",
  128.   /* 18 */  "UNKNOWN EXCEPTION",
  129.   /* 19 */  "UNKNOWN EXCEPTION",
  130.   /* 20 */  "UNKNOWN EXCEPTION",
  131.   /* 21 */  "UNKNOWN EXCEPTION",
  132.   /* 22 */  "UNKNOWN EXCEPTION",
  133.   /* 23 */  "UNKNOWN EXCEPTION",
  134.   /* 24 */  "Spurious Interrupt",
  135.   /* 25 */  "Level 1 Interrupt",
  136.   /* 26 */  "Level 2 Interrupt",
  137.   /* 27 */  "Level 3 Interrupt",
  138.   /* 28 */  "Level 4 Interrupt",
  139.   /* 29 */  "Level 5 Interrupt",
  140.   /* 30 */  "Level 6 Interrupt",
  141.   /* 31 */  "Level 7 Interrupt",
  142.   /* 32 */  "TRAP #0",
  143.   /* 33 */  "Syscall Trap",
  144.   /* 34 */  "Signal Return Trap",
  145.   /* 35 */  "Bad Trap",
  146.   /* 36 */  "TRAP #4",
  147.   /* 37 */  "TRAP #5",
  148.   /* 38 */  "TRAP #6",
  149.   /* 39 */  "TRAP #7",
  150.   /* 40 */  "TRAP #8",
  151.   /* 41 */  "TRAP #9",
  152.   /* 42 */  "TRAP #10",
  153.   /* 43 */  "TRAP #11",
  154.   /* 44 */  "TRAP #12",
  155.   /* 45 */  "TRAP #13",
  156.   /* 46 */  "TRAP #14",
  157.   /* 47 */  "Breakpoint Trap",
  158.   /* 48 */  "FPU Unordered Condition",
  159.   /* 49 */  "FPU Inexact Result",
  160.   /* 50 */  "FPU Zero Divide",
  161.   /* 51 */  "FPU Underflow",
  162.   /* 52 */  "FPU Operand Error",
  163.   /* 53 */  "FPU Overflow",
  164.   /* 54 */  "FPU NaN",
  165.   /* 55 */  "UNKNOWN EXCEPTION",
  166. };
  167.  
  168. /*
  169.  * The type of machine that we are on.
  170.  */
  171. int        machineType;
  172.  
  173. /*
  174.  * Whether syslog should remain diverted on continue or not.
  175.  */
  176. static Boolean    syslogDiverted = FALSE;
  177.  
  178. /*
  179.  * This is a typedef which is used to take care of the hole that is put in
  180.  * the stack when we are called.
  181.  */
  182. typedef struct {
  183.     char    hole[DBG_STACK_HOLE];
  184. } StackHole;
  185.  
  186. /*
  187.  * All of the stuff that is put onto the stack when the debugger is entered.
  188.  */
  189. typedef struct {
  190.     int            gprs[MACH_NUM_GPRS];
  191.     Mach_TrapStack    trapStack;
  192. } DbgStack;
  193.  
  194. /*
  195.  * Declare global variables.
  196.  */
  197. int        dbgSfcReg;
  198. int        dbgDfcReg;
  199. int         dbgUserContext;
  200. int         dbgKernelContext;
  201. DbgStack    dbgGlobalStack;
  202. int        dbgTermReason;
  203. int        dbgInDebugger;
  204. int        dbgIntPending;
  205. int        dbgExcType;
  206. Boolean        dbgPanic;
  207. int        dbgSavedSP;
  208. int        dbgMaxStackAddr;
  209. Boolean        dbg_UsingSyslog = FALSE;
  210. Boolean        dbgCanUseSyslog = TRUE;
  211. static       int    oldContext;
  212.  
  213. /*
  214.  * Saved exception stack stuff.
  215.  */
  216. static    int        savedDbgStackLength;
  217. static    int        savedExcStackLength;
  218. static    DbgStack    savedDbgStack;
  219. static    Boolean        callInProgress = FALSE;
  220.  
  221. /* 
  222.  * Forward declarations:
  223.  */
  224. static void DbgCheckNmis _ARGS_((void));
  225. static char *    TranslateOpcode _ARGS_((Dbg_Opcode opcode));
  226. static char *    TranslateException _ARGS_((int exception));
  227. static Boolean    ReadRequest _ARGS_((Boolean timeout));
  228. static void    SendReply _ARGS_((void));
  229. static void    GetRequestBytes _ARGS_((int numBytes, Address dest));
  230. static void    PutReplyBytes _ARGS_((int numBytes, Address src));
  231.  
  232. extern    void    Dbg_Main _ARGS_((StackHole stackHole,
  233.                  DbgStack dbgStack));
  234.                 /* called from assembly code? */
  235.  
  236. /*
  237.  * ----------------------------------------------------------------------------
  238.  *
  239.  * DbgCheckNmis --
  240.  *
  241.  *    Turn Non-maskable-interrupts on and off to allow keyboard events to
  242.  *    take place.  Only needed on Sun-2's because of the funny mapping
  243.  *    between kernel and user address spaces - they are turned on in the
  244.  *    main debugging loop on Sun-3's.
  245.  *
  246.  * Results:
  247.  *     None.
  248.  *
  249.  * Side effects:
  250.  *     None.
  251.  *
  252.  * ----------------------------------------------------------------------------
  253.  */
  254. static void
  255. DbgCheckNmis()
  256. {
  257. #ifdef sun2
  258.     int    oldContext;
  259.     oldContext = VmMachGetKernelContext(); 
  260.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  261.     Mach_MonStartNmi();
  262.     Mach_MonStopNmi();
  263.     VmMachSetKernelContext(oldContext);
  264. #endif
  265. }
  266.  
  267.  
  268. /*
  269.  * ----------------------------------------------------------------------------
  270.  *
  271.  * Dbg_InRange --
  272.  *
  273.  *     Return true if the given address is a valid kernel address and false
  274.  *     otherwise.
  275.  *
  276.  * Results:
  277.  *     True if the given address is a valid kernel address and false
  278.  *     otherwise.
  279.  *
  280.  * Side effects:
  281.  *     None.
  282.  *
  283.  * ----------------------------------------------------------------------------
  284.  */
  285. Boolean Dbg_InRange(addr, numBytes, writeable) 
  286.     unsigned     int addr;     /* Beginning address to check. */
  287.     int        numBytes;     /* Number of bytes to check. */
  288.     Boolean    writeable;    /* TRUE => address must be writeable. */
  289. {
  290.     VmMachPTE        pte;
  291.     int            i;
  292.     unsigned    int    prot;
  293.     int            firstPage;
  294.     int            lastPage;
  295.     unsigned    int    maxAddr;
  296.  
  297. #ifdef sun2
  298.     maxAddr = 0x1000000;
  299. #else
  300.     /*
  301.      * Don't look at anything in device space. 
  302.      */
  303.     maxAddr = 0x10000000;
  304. #endif
  305.     if (addr > maxAddr || (addr + numBytes - 1) > maxAddr) {
  306.     return(FALSE);
  307.     }
  308.     /*
  309.      * Don't look at anything in device space. 
  310.      */
  311.     if (!(((addr + numBytes - 1) < VMMACH_DEV_START_ADDR) ||
  312.      (addr >= VMMACH_DMA_START_ADDR))) {
  313.     return FALSE;
  314.     }
  315.     if ((int) (addr) & 0x1) {
  316.     printf("Dbg: odd address: %x\n", addr);
  317.     return(FALSE);
  318.     }
  319.  
  320.     firstPage = ((unsigned int) addr) >> VMMACH_PAGE_SHIFT;
  321.     lastPage = (((unsigned int) addr) + numBytes - 1) >> VMMACH_PAGE_SHIFT;
  322.     for (i = firstPage; i <= lastPage; i++) {
  323.     pte = VmMachGetPageMap((Address)(i << VMMACH_PAGE_SHIFT));
  324.     prot = pte & VMMACH_PROTECTION_FIELD;
  325.     if (!(pte & VMMACH_RESIDENT_BIT)) {
  326.         return(FALSE);
  327.     } else if (writeable) {
  328.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT) {
  329.         return(FALSE);
  330.         }
  331.     } else {
  332.         if (prot != VMMACH_KRW_PROT && prot != VMMACH_URW_PROT &&
  333.         prot != VMMACH_KR_PROT && prot != VMMACH_UR_PROT) {
  334.         return(FALSE);
  335.         }
  336.     }
  337.     }
  338.  
  339.     return(TRUE);
  340. }
  341.  
  342.  
  343. /*
  344.  * ----------------------------------------------------------------------------
  345.  *
  346.  * TranslateOpcode --
  347.  *
  348.  *     Return the string which describes the given opcode.
  349.  *
  350.  * Results:
  351.  *     The string which describes the given opcode.
  352.  *
  353.  * Side effects:
  354.  *     None.
  355.  *
  356.  * ----------------------------------------------------------------------------
  357.  */
  358. char *
  359. TranslateOpcode(opcode)
  360.     Dbg_Opcode opcode;        /* The opcode which is to be translated. */
  361. {
  362.     int index;
  363.  
  364.     index = (int) opcode;
  365.     if (index < 0 || index > (int) DBG_UNKNOWN) {
  366.         index = (int) DBG_UNKNOWN;
  367.     }
  368.  
  369.     return(opcodeNames[index]);
  370. }
  371.  
  372.  
  373. /*
  374.  * ----------------------------------------------------------------------------
  375.  *
  376.  * TranslateException --
  377.  *
  378.  *     Return the string that describes the given exception.
  379.  *
  380.  * Results:
  381.  *     None.
  382.  *
  383.  * Side effects:
  384.  *     None.
  385.  *
  386.  * ----------------------------------------------------------------------------
  387.  */
  388. char *
  389. TranslateException(exception)
  390.     int exception;        /* The exception which is to be translated. */
  391. {
  392.  
  393.     if (exception < 0 || exception > MACH_UNKNOWN_EXC) {
  394.         exception = MACH_UNKNOWN_EXC;
  395.     }
  396.  
  397.     return(exceptionNames[exception]);
  398. }
  399.  
  400.  
  401. /*
  402.  * ----------------------------------------------------------------------------
  403.  *
  404.  * DbgComplain --
  405.  *
  406.  *     Complain because we are already in the debugger.
  407.  *
  408.  * Results:
  409.  *     None.
  410.  *
  411.  * Side effects:
  412.  *     None.
  413.  *
  414.  * ----------------------------------------------------------------------------
  415.  */
  416. void
  417. DbgComplain(trapStack)
  418.     Mach_TrapStack    trapStack;
  419. {
  420.     printf("%s exception in the debugger at pc %x addr %x\n",
  421.        TranslateException(trapStack.trapType), 
  422.        trapStack.excStack.pc,
  423.        trapStack.excStack.tail.addrBusErr.faultAddr);
  424.     Mach_MonAbort();
  425. }
  426.  
  427.  
  428. /*
  429.  * ----------------------------------------------------------------------------
  430.  *
  431.  * Dbg_Init --
  432.  *
  433.  *     Initialize the debugger.
  434.  *
  435.  * Results:
  436.  *     None.
  437.  *
  438.  * Side effects:
  439.  *     dbgMonPC and dbgDoTrace are initialized.
  440.  *
  441.  * ----------------------------------------------------------------------------
  442.  */
  443. void
  444. Dbg_Init()
  445. {
  446.     dbgMonPC = 0;
  447.     dbgTraceLevel = 0;
  448.     dbgInDebugger = 0;
  449.     dbgIntPending = 0;
  450.     dbgPanic = FALSE;
  451.     dbg_BeingDebugged = FALSE;
  452.     machineType = Mach_GetMachineType();
  453.     Mach_MonPrintf("Machine type %d\n", machineType);
  454. }
  455.  
  456.  
  457. /*
  458.  * ----------------------------------------------------------------------------
  459.  *
  460.  * Dbg_InputPacket --
  461.  *
  462.  *     See if the current packet is for us.  At the moment this only 
  463.  *    handles ethernet packets.
  464.  *
  465.  *
  466.  * Results:
  467.  *     None.
  468.  *
  469.  * Side effects:
  470.  *     gotPacket is set to true if we got a packet that we liked.
  471.  *
  472.  * ----------------------------------------------------------------------------
  473.  */
  474. void
  475. Dbg_InputPacket(interPtr, packetPtr, packetLength)
  476.     Net_Interface    *interPtr;
  477.     Address        packetPtr;
  478.     int            packetLength;
  479. {
  480.     Address    dataPtr;
  481.     int        dataLength;
  482.     Net_EtherHdr    *etherHdrPtr;
  483.  
  484.     if (interPtr->netType != NET_NETWORK_ETHER) {
  485.     printf("Got a debugger packet on non-ethernet interface %s\n",
  486.         interPtr->name);
  487.     return;
  488.     }
  489.     etherHdrPtr = (Net_EtherHdr *)packetPtr;
  490.     if (etherHdrPtr->type != NET_ETHER_IP) {
  491.     if (dbgTraceLevel >= 5) {
  492.         printf("Non-IP (Type=0x%x) ", (int)etherHdrPtr->type);
  493.     }
  494.     return;
  495.     }
  496.     if (gotPacket) {
  497.     if (dbgTraceLevel >= 4) {
  498.         printf("Already have a packet.\n");
  499.     }
  500.     return;
  501.     }
  502.     if (dbgTraceLevel >= 4) {
  503.     printf("Validating packet\n");
  504.     }
  505.     if (Dbg_ValidatePacket(packetLength - sizeof(Net_EtherHdr),
  506.                (Net_IPHeader *)(packetPtr + sizeof(Net_EtherHdr)),
  507.                &dataLength, &dataPtr,
  508.                &dbgMyIPAddr, &dbgSrcIPAddr, &dbgSrcPort)) {
  509.     if (dbgTraceLevel >= 4) {
  510.         printf("Got a packet: length=%d\n", dataLength);
  511.     }
  512.     bcopy((Address)etherHdrPtr, (Address)&dbgEtherHdr,
  513.         sizeof(Net_EtherHdr));
  514.     gotPacket = TRUE;
  515.     bcopy(dataPtr, requestBuffer, dataLength);
  516.     /*
  517.      * Set the interface we are using. 
  518.      */
  519.     dbgInterPtr = interPtr;
  520.     }
  521. }
  522.  
  523.  
  524. /*
  525.  * ----------------------------------------------------------------------------
  526.  *
  527.  * ReadRequest --
  528.  *
  529.  *     Read the next request from kdbx.
  530.  *
  531.  * Results:
  532.  *     None.
  533.  *
  534.  * Side effects:
  535.  *     TRUE if didn't time out.
  536.  *
  537.  * ----------------------------------------------------------------------------
  538.  */
  539. static Boolean
  540. ReadRequest(timeout)
  541.     Boolean    timeout;    /* TRUE if should timeout after waiting a 
  542.                  * while. */
  543. {
  544.     int    timeOutCounter;
  545.     Net_Interface    *interPtr;
  546.     int        i;
  547.  
  548.     gotPacket = FALSE;
  549.     timeOutCounter = dbgTimeout;
  550.     do {
  551.         DbgCheckNmis();
  552.         /*
  553.          * Listen on all the interfaces. The debugger is relatively
  554.          * stateless so its easiest to just listen on them all.
  555.          */
  556.         for (i = 0; ; i++) {
  557.         interPtr = Net_NextInterface(TRUE, &i);
  558.         if (interPtr == (Net_Interface *) NIL) {
  559.             break;
  560.         }
  561.         Net_RecvPoll(interPtr);
  562.         if (gotPacket) {
  563.             break;
  564.         }
  565.         }
  566.         if (timeout) {
  567.         timeOutCounter--;
  568.         }
  569.     } while(!gotPacket && timeOutCounter != 0);
  570.     if (gotPacket) {
  571.         replyOffset = PACKET_HDR_SIZE;
  572.         requestOffset = 4;
  573.         curMsgNum = *(int *)(requestBuffer);
  574.         if (dbgTraceLevel >= 4) {
  575.         printf("MsgNum = %d\n", curMsgNum);
  576.         }
  577.     }
  578.  
  579.     return(gotPacket);
  580. }
  581.  
  582.  
  583. /*
  584.  * ----------------------------------------------------------------------------
  585.  *
  586.  * GetRequestBytes --
  587.  *
  588.  *     Get the next numBytes bytes from the current request.
  589.  *
  590.  * Results:
  591.  *     None.
  592.  *
  593.  * Side effects:
  594.  *     None.
  595.  *
  596.  * ----------------------------------------------------------------------------
  597.  */
  598. static void
  599. GetRequestBytes(numBytes, dest)
  600.     int        numBytes;
  601.     Address    dest;
  602. {
  603.     bcopy(requestBuffer + requestOffset, dest, numBytes);
  604.     requestOffset += numBytes;
  605. }
  606.  
  607.  
  608. /*
  609.  * ----------------------------------------------------------------------------
  610.  *
  611.  * PutReplyBytes --
  612.  *
  613.  *     Put the given bytes into the reply buffer.
  614.  *
  615.  * Results:
  616.  *     None.
  617.  *
  618.  * Side effects:
  619.  *     None.
  620.  *
  621.  * ----------------------------------------------------------------------------
  622.  */
  623. static void
  624. PutReplyBytes(numBytes, src)
  625.     int        numBytes;
  626.     Address    src;
  627. {
  628.     if (replyOffset + numBytes > DBG_MAX_REPLY_SIZE) {
  629.     printf("PutReplyBytes: Buffer overflow\n");
  630.     numBytes = DBG_MAX_REPLY_SIZE - replyOffset;
  631.     }
  632.     bcopy(src, &replyBuffer[replyOffset], numBytes);
  633.     replyOffset += numBytes;
  634. }
  635.  
  636.  
  637. /*
  638.  * ----------------------------------------------------------------------------
  639.  *
  640.  * SendReply --
  641.  *
  642.  *     Send a reply to kdbx.
  643.  *
  644.  * Results:
  645.  *     None.
  646.  *
  647.  * Side effects:
  648.  *     None.
  649.  *
  650.  * ----------------------------------------------------------------------------
  651.  */
  652. static void
  653. SendReply()
  654. {
  655.     Net_EtherHdr        *etherHdrPtr;
  656.  
  657.     if (dbgTraceLevel >= 4) {
  658.         printf("Sending reply\n");
  659.     }
  660.     etherHdrPtr = (Net_EtherHdr *) replyBuffer;
  661.     etherHdrPtr->source = dbgEtherHdr.destination;
  662.     etherHdrPtr->destination = dbgEtherHdr.source;
  663.     etherHdrPtr->type = dbgEtherHdr.type;
  664.     dbgGather.bufAddr = replyBuffer + sizeof(Net_EtherHdr);
  665.     dbgGather.length = replyOffset - sizeof(Net_EtherHdr);
  666.     dbgGather.mutexPtr = (Sync_Semaphore *) NIL;
  667.     *(int *)(replyBuffer + PACKET_HDR_SIZE - 4) = curMsgNum;
  668.     Dbg_FormatPacket(dbgMyIPAddr, dbgSrcIPAddr, dbgSrcPort,
  669.              replyOffset - sizeof(Net_EtherHdr) - Dbg_PacketHdrSize(),
  670.              replyBuffer + sizeof(Net_EtherHdr));
  671.     Net_RawOutput(dbgInterPtr, (Address) etherHdrPtr, &dbgGather, 1);
  672.     if (dbgTraceLevel >= 4) {
  673.         printf("Sent reply\n");
  674.     }
  675. }
  676.  
  677. /*
  678.  * 68020 and 68010 moveml instructions work differently.  68010 stores
  679.  * original value of sp and 68020 stores sp - 4.  This has to be fixed
  680.  * when getting around the exception stack.
  681.  */
  682. #ifdef sun3
  683. #define STACK_INC    4
  684. #endif
  685. #ifdef sun2
  686. #define STACK_INC    0
  687. #endif
  688.  
  689. /*
  690.  * ----------------------------------------------------------------------------
  691.  *
  692.  * Dbg_Main --
  693.  *
  694.  *     The main debugger loop.  This will read commands from the rs232 line
  695.  *     and call the proper routine to execute them.
  696.  *
  697.  * Results:
  698.  *     None.
  699.  *
  700.  * Side effects:
  701.  *     None.
  702.  *
  703.  * ----------------------------------------------------------------------------
  704.  */
  705. /*ARGSUSED*/
  706. void
  707. Dbg_Main(stackHole, dbgStack)
  708.     StackHole        stackHole;    /* The hole put in the stack so that
  709.                      * kdbx can play around with the stack*/
  710.     DbgStack        dbgStack;    /* All of the stuff that is put onto the
  711.                      * stack because of the exception and
  712.                      * the trap handler. */
  713. {
  714.     short        trapCode;    /* Reason that we trapped that is sent
  715.                      * to kdbx. */
  716.     Boolean          done;        /* Boolean to tell us whether to leave
  717.                      * the main debugger loop */
  718.     int              dbgStackLength;/* The length of the trap stack */
  719.     int              excStackLength;    /* The length of the exception part 
  720.                      * of the trap stack */
  721.     Dbg_Opcode          opcode;        /* The operation that was requested */
  722.     short          tOpcode;    /* Temporary used to receive the opcode
  723.                      * which is sent as a short. */
  724.                     /* Process table entry that we switched
  725.                      * stacks to. */
  726.     Proc_ControlBlock    *procPtr = (Proc_ControlBlock *) NIL;
  727.     Boolean        atInterruptLevel;/* TRUE if we were entered from an
  728.                       * interrupt handler. */
  729.  
  730. #ifdef sun3
  731.     /*
  732.      * Turn on non-maskable interrupts.
  733.      */
  734.     Mach_MonStartNmi();
  735. #endif
  736.     /*
  737.      * Switch to kernel context so that we can access the monitor.
  738.      */
  739.     oldContext = VmMachGetKernelContext();
  740.     VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  741.  
  742. #ifdef NOTDEF
  743. /*
  744.  * This code causes machines to seem to pop out of the debugger.
  745.  */
  746.     if (!dbg_BeingDebugged) {
  747.         /*
  748.          * Try to sync the disks if we aren't at interrupt level.  If we
  749.          * are don't bother because we'll just hang waiting for interrupts.
  750.          * Of course I could force interrupts to be enabled but I'm not sure
  751.          * if that's a great idea.
  752.          */
  753.         if (mach_NumDisableIntrsPtr[0] == 0 && !mach_AtInterruptLevel) {
  754.             Mach_EnableIntr();
  755.             Sys_SyncDisks(!MACH_BRKPT_TRAP);
  756.             dbg_SyncedDisks = TRUE;
  757.             Mach_DisableIntr();
  758.         }
  759.     }
  760. #endif NOTDEF
  761.  
  762.     /*
  763.      * Put us at interrupt level so that printf won't accidently enable
  764.      * interrupts.
  765.      */
  766.     atInterruptLevel = mach_AtInterruptLevel;
  767.     mach_AtInterruptLevel = TRUE;
  768.  
  769.  
  770.     /*
  771.      * Force system log output to the console.
  772.      */
  773.     if (!syslogDiverted) {
  774.     Dev_SyslogDebug(TRUE);
  775.     }
  776.  
  777.     /*
  778.      * We want to inform the user what caused the problem.  However we only
  779.      * tell him if: 1) we are debugging the debugger; 2) we are not under 
  780.      * debugger control (i.e. we don't want to inform the user on every trace 
  781.      * trap), 3) we got something besides a trace trap or a breakpoint trap
  782.      * exception.
  783.      */
  784.     if (dbgTraceLevel >= 1 || !dbg_BeingDebugged || 
  785.         (dbgStack.trapStack.trapType != MACH_TRACE_TRAP && 
  786.          dbgStack.trapStack.trapType != MACH_BRKPT_TRAP)) { 
  787.     Dev_VidEnable(TRUE);    /* unblank the screen */
  788.     printf("Entering debugger with a %s exception at PC 0x%x\r\n",
  789.            TranslateException(dbgStack.trapStack.trapType),
  790.            (unsigned) dbgStack.trapStack.excStack.pc);
  791.     }
  792.  
  793.     /*
  794.      * The saved stack pointer points to all of the junk on the stack from
  795.      * the exception.  We need to move the saved stack pointer past all of
  796.      * this junk to the point where kdbx sees what it expects (it doesn't 
  797.      * understand exception stacks).  Also we need to copy all of the 
  798.      * trap stack to a global variable.  This allows access to this stack 
  799.      * through the debugger (kdbx doesn't know we are in this routine so the
  800.      * parameter dbgStack cannot be printed out in kdbx).
  801.      *
  802.      * NOTE:
  803.      *
  804.      * When kdbx does a "call" command it adds things onto the stack starting 
  805.      * from the saved stack pointer.  When it does this it will trash the 
  806.      * trap stack that we were passed.  Thus saving a copy of the trap
  807.      * stack also serves the purpose of preventing kdbx from trashing the
  808.      * original copy.
  809.      */
  810.     excStackLength = Mach_GetExcStackSize(&dbgStack.trapStack.excStack);
  811.     dbgStackLength = sizeof(DbgStack) - sizeof(Mach_ExcStack) + excStackLength;
  812.  
  813.     bcopy((Address) &dbgStack, (Address) &dbgGlobalStack, dbgStackLength);
  814.  
  815.     dbgGlobalStack.gprs[SP] += excStackLength + STACK_INC + 
  816.                    MACH_TRAP_INFO_SIZE;
  817.  
  818.     /*
  819.      * Clear the trace bit from the status register.
  820.      */
  821.     dbgGlobalStack.trapStack.excStack.statusReg &= ~MACH_SR_TRACEMODE;
  822.  
  823.     /*
  824.      * We need to tell kdbx what type of exception this is.  If the
  825.      * termReason is DBG_INTERRUPT_SIG then we set the trap code to
  826.      * interrupted.  Otherwise we don't know what caused us to get here so
  827.      * we have to check the exception type.  If the exception is either a
  828.      * trace trap of a breakpoint trap then we set the term reason to
  829.      * DBG_TRACE_TRAP_SIG and set the trap code appropriately.  Otherwise we 
  830.      * tell kdbx that the reason was an DBG_INTERRUPT_SIG and we set the trap
  831.      * code appropriately for the given exception.
  832.      */
  833.     trapCode = dbgStack.trapStack.trapType;
  834.     if (dbgTermReason == DBG_INTERRUPT_SIG) {
  835.     trapCode = DBG_INTERRUPT;
  836.     } else if (dbgPanic) {
  837.     dbgPanic = FALSE;
  838.     trapCode = DBG_INTERRUPT;
  839.         dbgTermReason = DBG_INTERRUPT_SIG;
  840.     } else if (dbgStack.trapStack.trapType == MACH_TRACE_TRAP ||
  841.            dbgStack.trapStack.trapType == MACH_BRKPT_TRAP) {
  842.     dbgTermReason = DBG_TRACE_TRAP_SIG;
  843.     } else {
  844.     dbgTermReason = DBG_INTERRUPT_SIG;
  845.     }
  846.  
  847.     dbg_UsingNetwork = TRUE;
  848.  
  849.     /*
  850.      * If we are stopped after a continue or single step must write a
  851.      * null byte to the debugger at the other end.  It knows that if it sees
  852.      * a null byte we are stopped at this end.
  853.      */
  854.     if (dbg_BeingDebugged) {
  855.     unsigned    char    ch;
  856.  
  857.     ch = 0;
  858.     PutReplyBytes(1, (Address)&ch);
  859.     SendReply();
  860.     do {
  861.         if (ReadRequest(TRUE)) {
  862.         GetRequestBytes(2, (Address)&tOpcode);
  863.         opcode = (Dbg_Opcode) tOpcode;
  864.         if (opcode == DBG_GET_STOP_INFO) {
  865.             break;
  866.         }
  867.         }
  868.         /*
  869.          * We can only timeout if we are using network debugging.
  870.          */
  871.         Net_RawOutput(dbgInterPtr, (Address) replyBuffer, 
  872.             &dbgGather, 1);
  873.         if (dbgTraceLevel >= 5) {
  874.         printf("DBG: Timeout\n");
  875.         }
  876.         printf("TI ");
  877.     } while (TRUE);
  878.     } else {
  879.     (void) ReadRequest(FALSE);
  880.     GetRequestBytes(2, (Address)&tOpcode);
  881.     opcode = (Dbg_Opcode) tOpcode;
  882.     }
  883.  
  884.     /*
  885.      * Now read commands until kdbx tells us that we can return.
  886.      */
  887.     done = FALSE;
  888.     while (!done) {
  889.     if (dbgTraceLevel >= 2) {
  890.         printf("Request: %s ", TranslateOpcode(opcode));
  891.     }
  892.  
  893.     /*
  894.      * Process the request 
  895.      */
  896.     switch (opcode) {
  897.  
  898.         /*
  899.          * The client wants to read some data from us ...
  900.          */
  901.  
  902.         case DBG_GET_STOP_INFO: {
  903.         StopInfo    stopInfo;
  904.         extern void    Mach_ContextSwitch();
  905.         stopInfo.codeStart = (int)mach_CodeStart;
  906.         if (procPtr != (Proc_ControlBlock *) NIL &&
  907.             procPtr->machStatePtr != (Mach_State *)NIL) {
  908.             stopInfo.maxStackAddr =
  909.             (int)(procPtr->machStatePtr->kernStackStart + 
  910.                   mach_KernStackSize);
  911.             bcopy((Address) procPtr->machStatePtr->switchRegs,
  912.                 (Address) stopInfo.genRegs,
  913.                 sizeof(procPtr->machStatePtr->switchRegs));
  914.             stopInfo.pc = (int) ((Address) Mach_ContextSwitch);
  915.         } else {
  916.             stopInfo.maxStackAddr = dbgMaxStackAddr;
  917.             bcopy((Address) dbgGlobalStack.gprs, 
  918.                 (Address) stopInfo.genRegs,
  919.                 sizeof(dbgGlobalStack.gprs));
  920.             stopInfo.pc = dbgGlobalStack.trapStack.excStack.pc;
  921.         }
  922.         stopInfo.termReason = dbgTermReason;
  923.         stopInfo.trapCode = trapCode;
  924.         stopInfo.statusReg = 
  925.         (unsigned short) dbgGlobalStack.trapStack.excStack.statusReg;
  926.         PutReplyBytes(sizeof(stopInfo), (Address)&stopInfo);
  927.         SendReply();
  928.         break;
  929.         }
  930.         case DBG_READ_ALL_GPRS:
  931.         if (procPtr != (Proc_ControlBlock *) NIL &&
  932.             procPtr->machStatePtr != (Mach_State *)NIL) {
  933.             PutReplyBytes(sizeof(procPtr->machStatePtr->switchRegs),
  934.                  (Address) procPtr->machStatePtr->switchRegs);
  935.         } else {
  936.             PutReplyBytes(sizeof(dbgGlobalStack.gprs),
  937.                      (Address) dbgGlobalStack.gprs);
  938.         }
  939.         SendReply();
  940.         break;
  941.  
  942.         case DBG_GET_DUMP_BOUNDS: {
  943.         Dbg_DumpBounds bounds;
  944.         extern unsigned int end;
  945.         bounds.pageSize = vm_PageSize;
  946.         bounds.stackSize = mach_KernStackSize;
  947.         bounds.kernelCodeStart = (unsigned int) mach_KernStart;
  948.         bounds.kernelCodeSize  = 
  949.             (unsigned int) (((Address)(&end)) - mach_KernStart);
  950.         bounds.kernelDataStart    = ((unsigned int)(&end));
  951.         bounds.kernelDataSize    = (unsigned int) 
  952.                 (vmMemEnd - ((Address)(&end)));
  953.         bounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  954.         bounds.kernelStacksSize = (unsigned int) 
  955.                 (vmStackEndAddr - vmStackBaseAddr);
  956.         bounds.fileCacheStart    = (unsigned int)vmBlockCacheBaseAddr;
  957.         bounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr - 
  958.                         vmBlockCacheBaseAddr);
  959.  
  960.         PutReplyBytes(sizeof(bounds), (char *)&bounds);
  961.         SendReply();
  962.         break;
  963.         }
  964.         
  965.         case DBG_GET_VERSION_STRING: {
  966.         char    *version;
  967.  
  968.         version = SpriteVersion();
  969.         PutReplyBytes(strlen(version) + 1, version);
  970.         SendReply();
  971.         break;
  972.         }
  973.         case DBG_INST_READ:
  974.         case DBG_DATA_READ: {
  975.         Dbg_ReadMem    readMem;
  976.         int        status;
  977.  
  978.         GetRequestBytes(sizeof(readMem), (Address) &readMem); 
  979.         if (dbgTraceLevel >= 2) {
  980.             printf("Addr=%x Numbytes=%d ",
  981.                 readMem.address, readMem.numBytes);
  982.         }
  983.  
  984.         VmMachSetKernelContext(oldContext);
  985.         if (Dbg_InRange((unsigned int) readMem.address, readMem.numBytes,
  986.                 FALSE)) {
  987.             status = 1;
  988.             PutReplyBytes(sizeof(status), (Address)&status);
  989.             PutReplyBytes(readMem.numBytes, (Address)readMem.address);
  990.         } else {
  991.             if (dbgTraceLevel >= 2) {
  992.             printf("FAILURE ");
  993.             }
  994.             status = 0;
  995.             PutReplyBytes(sizeof(status), (Address)&status);
  996.         }
  997.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  998.         SendReply();
  999.         break;
  1000.         }
  1001.  
  1002.         /*
  1003.          * The client wants to write something to us.
  1004.          */
  1005.         case DBG_SET_PID: {
  1006.         Proc_PID    pid;
  1007.  
  1008.         GetRequestBytes(sizeof(pid), (Address) &pid);
  1009.         {
  1010.             int    dummy;
  1011.  
  1012.             PutReplyBytes(4, (Address) &dummy);
  1013.             SendReply();
  1014.         }
  1015.         if (dbgTraceLevel >= 2) {
  1016.             printf("pid %x ", pid);
  1017.         }
  1018.         if (pid == 0) {
  1019.             procPtr = (Proc_ControlBlock *) NIL;
  1020.         } else {
  1021.             procPtr = Proc_GetPCB(pid);
  1022.             if (procPtr == (Proc_ControlBlock *) NIL ||
  1023.                 procPtr == (Proc_ControlBlock *) 0 ||
  1024.             procPtr->state == PROC_UNUSED ||
  1025.                 procPtr->state == PROC_DEAD ||
  1026.             procPtr->state == PROC_NEW) {
  1027.             printf("Can't backtrace stack for process %x\n",
  1028.                     pid);
  1029.             procPtr = (Proc_ControlBlock *) NIL;
  1030.             }
  1031.         }
  1032.         break;
  1033.         }
  1034.         case DBG_REBOOT: {
  1035.         int    stringLength;
  1036.         char    rebootString[100];
  1037.         /*
  1038.          * For a reboot command first read the size of the string and
  1039.          * then the string itself.
  1040.          */
  1041.         GetRequestBytes(sizeof(int), (Address)&stringLength);
  1042.         if (stringLength != 0) {
  1043.             GetRequestBytes(stringLength, (Address)rebootString);
  1044.         }
  1045.         rebootString[stringLength] = '\0';
  1046.         {
  1047.             int    dummy;
  1048.  
  1049.             PutReplyBytes(4, (Address) &dummy);
  1050.             SendReply();
  1051.         }
  1052.         Mach_MonReboot(rebootString);
  1053.         }
  1054.         case DBG_INST_WRITE:
  1055.         case DBG_DATA_WRITE: {
  1056.         Dbg_WriteMem        writeMem;
  1057.         unsigned    char    ch;
  1058.         /*
  1059.          * For an instruction or a data write we first have to find out 
  1060.          * which address to write to and how many bytes to write.  Next
  1061.          * we have to make sure that the address is valid.  If it is
  1062.          * then we read the data and write it to the given address.  If
  1063.          * not we just report an error to kdbx.
  1064.          */
  1065.         GetRequestBytes(2 * sizeof(int), (Address) &writeMem);
  1066.         if (dbgTraceLevel >= 2) {
  1067.             printf("Addr=%x Numbytes=%d ",
  1068.                 writeMem.address, writeMem.numBytes);
  1069.         }
  1070.  
  1071.         VmMachSetKernelContext(oldContext);
  1072.         if (Dbg_InRange((unsigned int) writeMem.address,
  1073.                 writeMem.numBytes, opcode == DBG_DATA_WRITE)) {
  1074.             if (opcode == DBG_INST_WRITE) {
  1075.             VmMach_SetProtForDbg(TRUE, writeMem.numBytes, 
  1076.                          (Address)writeMem.address);
  1077.             }
  1078.             GetRequestBytes(writeMem.numBytes,
  1079.                     (Address) writeMem.address);
  1080.             if (opcode == DBG_INST_WRITE) {
  1081.             VmMach_SetProtForDbg(FALSE, writeMem.numBytes, 
  1082.                          (Address)writeMem.address);
  1083.             }
  1084.             ch = 1;
  1085.         } else {
  1086.             char    buf[100];
  1087.  
  1088.             if (dbgTraceLevel >= 2) {
  1089.             printf("FAILURE ");
  1090.             }
  1091.             GetRequestBytes(writeMem.numBytes, buf);
  1092.             ch = 0;
  1093.         }
  1094.         VmMachSetKernelContext(VMMACH_KERN_CONTEXT);
  1095.  
  1096.         PutReplyBytes(1, (char *) &ch);
  1097.         SendReply();
  1098.  
  1099.         break;
  1100.         }
  1101.  
  1102.         case DBG_WRITE_GPR: {                
  1103.         Dbg_WriteGPR    writeGPR;
  1104.  
  1105.         /*
  1106.          * First find out which register is being written and
  1107.          * then read the value.
  1108.          */
  1109.         GetRequestBytes(sizeof(writeGPR), (Address)&writeGPR);
  1110.         {
  1111.             int    dummy;
  1112.  
  1113.             PutReplyBytes(4, (Address) &dummy);
  1114.             SendReply();
  1115.         }
  1116.         if (dbgTraceLevel >= 2) {
  1117.             printf("register %d data %x ", writeGPR.regNum, 
  1118.                 writeGPR.regVal);
  1119.         }
  1120.         dbgGlobalStack.gprs[writeGPR.regNum] = writeGPR.regVal;
  1121.         break;
  1122.         }
  1123.  
  1124.         case DBG_DIVERT_SYSLOG: 
  1125.         GetRequestBytes(sizeof(Boolean), (Address)&syslogDiverted);
  1126.         {
  1127.             int    dummy;
  1128.  
  1129.             PutReplyBytes(4, (Address) &dummy);
  1130.             SendReply();
  1131.         }
  1132.         break;
  1133.  
  1134.         case DBG_BEGIN_CALL:
  1135.         /*
  1136.          * We are beginning a call command.  Fix up the stack
  1137.          * so that we will be able to continue.  We will put
  1138.          * it back when we are done.
  1139.          */
  1140.         savedDbgStackLength = dbgStackLength;
  1141.         savedExcStackLength = excStackLength;
  1142.         bcopy((Address)&dbgGlobalStack, (Address)&savedDbgStack,
  1143.             dbgStackLength);
  1144.  
  1145.         dbgGlobalStack.trapStack.excStack.vor.stackFormat = MACH_SHORT;
  1146.         excStackLength =
  1147.             Mach_GetExcStackSize(&dbgGlobalStack.trapStack.excStack);
  1148.         dbgStackLength = excStackLength + sizeof(DbgStack) - 
  1149.                  sizeof(Mach_ExcStack);
  1150.  
  1151.         callInProgress = TRUE;
  1152.         if (dbgCanUseSyslog) {
  1153.             dbg_UsingSyslog = TRUE;
  1154.         }
  1155.           {
  1156.             int    dummy;
  1157.  
  1158.             PutReplyBytes(4, (Address) &dummy);
  1159.             SendReply();
  1160.         }
  1161.  
  1162.         break;
  1163.         case DBG_END_CALL: {
  1164.         char    *buffer;
  1165.         int    *firstIndexPtr;
  1166.         int    *lastIndexPtr;
  1167.         int    bufSize;
  1168.         int    length;
  1169.         if (callInProgress) {
  1170.             /*
  1171.              * Restore the state to the state before the
  1172.              * call was begun.  Note that the DBG_END_CALL command will
  1173.              * be executed until the sys log buffer is empty so only
  1174.              * need to restore our state if the callInProgress flag is
  1175.              * set.
  1176.              */
  1177.             dbgStackLength = savedDbgStackLength;
  1178.             excStackLength = savedExcStackLength;
  1179.             bcopy((Address)&savedDbgStack, (Address)&dbgGlobalStack,
  1180.                 sizeof(dbgGlobalStack));
  1181.             callInProgress = FALSE;
  1182.         }
  1183.         /*
  1184.          * Dump the syslog buffer.
  1185.          */
  1186.         Dev_SyslogReturnBuffer(&buffer, &firstIndexPtr,
  1187.                        &lastIndexPtr, &bufSize);
  1188.         if (*firstIndexPtr == -1) {
  1189.             length = 0;
  1190.             PutReplyBytes(4, (Address) &length);
  1191.             dbg_UsingSyslog = FALSE;
  1192.         } else if (*firstIndexPtr <= *lastIndexPtr) {
  1193.             length = *lastIndexPtr - *firstIndexPtr + 1;
  1194.             if (length + 4 > PACKET_DATA_SIZE) {
  1195.             length = PACKET_DATA_SIZE - 4;
  1196.             }
  1197.             PutReplyBytes(4, (Address) &length);
  1198.             PutReplyBytes(length,
  1199.                   (Address)&buffer[*firstIndexPtr]);
  1200.             *firstIndexPtr += length;
  1201.             if (*firstIndexPtr > *lastIndexPtr) {
  1202.             *firstIndexPtr = *lastIndexPtr = -1;
  1203.             }
  1204.         } else {
  1205.             length = bufSize - *firstIndexPtr;
  1206.             if (length + 4 > PACKET_DATA_SIZE) {
  1207.             length = PACKET_DATA_SIZE - 4;
  1208.             }
  1209.             PutReplyBytes(4, (Address) &length);
  1210.             PutReplyBytes(length,
  1211.                   (Address)buffer[*firstIndexPtr]);
  1212.             *firstIndexPtr += length;
  1213.             if (*firstIndexPtr == bufSize) {
  1214.             *firstIndexPtr = 0;
  1215.             }
  1216.         }
  1217.         SendReply();
  1218.         break;
  1219.         }
  1220.         case DBG_CALL_FUNCTION: {
  1221.         Dbg_CallFunc        callFunc;
  1222.         int            returnVal;
  1223.         static int        argBuf[128];
  1224.         GetRequestBytes(2 * sizeof(int), (Address) &callFunc);
  1225.         if (dbgTraceLevel >= 2) {
  1226.             printf("Addr=%x Numbytes=%d ",
  1227.                 callFunc.address, callFunc.numBytes);
  1228.         }
  1229.  
  1230.         if ((callFunc.numBytes >= 0 && callFunc.numBytes < 128) &&
  1231.              Dbg_InRange((unsigned int) callFunc.address,4,FALSE)) {
  1232.             GetRequestBytes(callFunc.numBytes,(Address) argBuf);
  1233.             returnVal = (* ((int (*)()) callFunc.address))(argBuf[0],
  1234.             argBuf[1],argBuf[2],argBuf[3],argBuf[4],argBuf[5],argBuf[6],
  1235.             argBuf[7],argBuf[8],argBuf[9]);
  1236.         } else {
  1237.  
  1238.             if (dbgTraceLevel >= 2) {
  1239.             printf("FAILURE ");
  1240.             }
  1241.             GetRequestBytes(callFunc.numBytes,(Address)argBuf);
  1242.             returnVal = -1;
  1243.         }
  1244.         PutReplyBytes(4, (char *) &returnVal);
  1245.         SendReply();
  1246.  
  1247.         break;
  1248.         }
  1249.         case DBG_CONTINUE: 
  1250.         /*
  1251.          * The client wants to continue execution.
  1252.          */
  1253.         GetRequestBytes(sizeof(int), 
  1254.                 (Address) &dbgGlobalStack.trapStack.excStack.pc);
  1255.         if (dbgTraceLevel >= 2) {
  1256.             printf("Continuing from pc %x ",
  1257.                 dbgGlobalStack.trapStack.excStack.pc);
  1258.         }
  1259.          {
  1260.             int    dummy;
  1261.  
  1262.             PutReplyBytes(4, (Address) &dummy);
  1263.             SendReply();
  1264.         }
  1265.  
  1266.         dbg_BeingDebugged = TRUE;
  1267.         done = TRUE;
  1268.         break;
  1269.  
  1270.         case DBG_SINGLESTEP:
  1271.         /*
  1272.          * The client wants to single step.
  1273.          */
  1274.         GetRequestBytes(sizeof(int), 
  1275.                 (Address) &dbgGlobalStack.trapStack.excStack.pc);
  1276.         if (dbgTraceLevel >= 2) {
  1277.             printf("Stepping from pc %x ",
  1278.                 dbgGlobalStack.trapStack.excStack.pc);
  1279.         }
  1280.          {
  1281.             int    dummy;
  1282.  
  1283.             PutReplyBytes(4, (Address) &dummy);
  1284.             SendReply();
  1285.         }
  1286.  
  1287.         /* 
  1288.          * Turn the trace bit on in the SR.
  1289.          */
  1290.         dbgGlobalStack.trapStack.excStack.statusReg |= 
  1291.                             MACH_SR_TRACEMODE;
  1292.         dbg_BeingDebugged = TRUE;
  1293.         done = TRUE;
  1294.         break;
  1295.  
  1296.         case DBG_DETACH:
  1297.         /*
  1298.          * The debugger has terminated and wants to let us go about our
  1299.          * business.
  1300.          */
  1301.         GetRequestBytes(sizeof(int), 
  1302.                 (Address) &dbgGlobalStack.trapStack.excStack.pc);
  1303.         if (dbgTraceLevel >= 2) {
  1304.             printf("Detaching at pc %x ",
  1305.                 dbgGlobalStack.trapStack.excStack.pc);
  1306.         }
  1307.          {
  1308.             int    dummy;
  1309.  
  1310.             PutReplyBytes(4, (Address) &dummy);
  1311.             SendReply();
  1312.         }
  1313.  
  1314.         dbg_BeingDebugged = FALSE;
  1315.         done = TRUE;
  1316.         printf("Sprite is now detached from the debugger\r\n");
  1317.         break;
  1318.  
  1319.         case DBG_UNKNOWN:
  1320.         printf("debugger: unrecognized request\n");
  1321.         break;
  1322.     }
  1323.  
  1324.     if (dbgTraceLevel >= 2) {
  1325.         printf("\r\n");
  1326.     }
  1327.     if (!done) {
  1328.         (void)ReadRequest(FALSE);
  1329.         GetRequestBytes(2, (Address)&tOpcode);
  1330.         opcode = (Dbg_Opcode) tOpcode;
  1331.     }
  1332.     }
  1333.  
  1334.     /*
  1335.      * Return from the debugger.  Before we return, we must push the trap
  1336.      * stuff back onto the stack and restore the saved sp to point to the
  1337.      * exception stuff on the stack.
  1338.      */
  1339.  
  1340.     dbgSavedSP = dbgGlobalStack.gprs[SP] - dbgStackLength;
  1341.     dbgGlobalStack.gprs[SP] -= excStackLength + STACK_INC  +
  1342.                       MACH_TRAP_INFO_SIZE;
  1343.     bcopy((Address) &dbgGlobalStack, (Address) dbgSavedSP, dbgStackLength);
  1344.  
  1345.     VmMachSetKernelContext(oldContext);
  1346.     mach_AtInterruptLevel = atInterruptLevel;
  1347.     dbg_UsingNetwork = FALSE;
  1348.  
  1349.     /*
  1350.      * Don't force system log output to the console.
  1351.      */
  1352.     if (!syslogDiverted) {
  1353.     Dev_SyslogDebug(FALSE);
  1354.     }
  1355. #ifdef sun3
  1356.     /*
  1357.      * Turn off non-maskable interrupts.
  1358.      */
  1359.     Mach_MonStopNmi();
  1360. #endif
  1361. }
  1362.